// This Pine Script® code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © AlbertSetups


 //@version=6
indicator("Apex Confluence Engine | Albert Setups", overlay=true, max_labels_count=150, max_lines_count=30, max_boxes_count=10)

//━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// SETTINGS
//━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
groupSMC = "Market Structure"
swingLen = input.int(5, "Swing Length", minval=2, maxval=20, group=groupSMC)
showStructure = input.bool(true, "Show BOS / CHoCH", group=groupSMC)
showSweeps = input.bool(true, "Show Liquidity Sweeps", group=groupSMC)

groupRSI = "Momentum Confirmation"
rsiLen = input.int(14, "RSI Length", minval=2, group=groupRSI)
buyRSI = input.int(52, "BUY RSI Threshold", minval=1, maxval=99, group=groupRSI)
sellRSI = input.int(48, "SELL RSI Threshold", minval=1, maxval=99, group=groupRSI)
useCandle = input.bool(true, "Require Candle Confirmation", group=groupRSI)

groupZones = "Fair Value Gaps"
showFVG = input.bool(true, "Show Latest FVGs", group=groupZones)
fvgExtend = input.int(20, "FVG Extension", minval=5, maxval=100, group=groupZones)

groupSignals = "Trade Signals"
showSignals = input.bool(true, "Show BUY / SELL Signals", group=groupSignals)
cooldown = input.int(3, "Bars Between Signals", minval=0, maxval=100, group=groupSignals)

groupTargets = "ATR Targets"
atrLen = input.int(14, "ATR Length", minval=1, group=groupTargets)
atrMult = input.float(2.0, "Target Distance (ATR)", minval=0.25, step=0.25, group=groupTargets)
showTargets = input.bool(true, "Show Latest ATR Target", group=groupTargets)
targetLength = input.int(20, "Target Line Length", minval=1, maxval=200, group=groupTargets)

//━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// RSI, ATR & CANDLE CONFIRMATION
//━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
rsiValue = ta.rsi(close, rsiLen)
atrValue = ta.atr(atrLen)

bullCandle = close > open
bearCandle = close < open

bullMomentum = rsiValue >= buyRSI
bearMomentum = rsiValue <= sellRSI

bullCandleOK = not useCandle or bullCandle
bearCandleOK = not useCandle or bearCandle

//━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// CONFIRMED MARKET STRUCTURE
//━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
pivotHigh = ta.pivothigh(high, swingLen, swingLen)
pivotLow = ta.pivotlow(low, swingLen, swingLen)

var float swingHigh = na
var float swingLow = na
var bool highBroken = false
var bool lowBroken = false
var int marketTrend = 0

if not na(pivotHigh)
    swingHigh := pivotHigh
    highBroken := false

if not na(pivotLow)
    swingLow := pivotLow
    lowBroken := false

bullBreak = barstate.isconfirmed and not na(swingHigh) and close > swingHigh and not highBroken
bearBreak = barstate.isconfirmed and not na(swingLow) and close < swingLow and not lowBroken

if bullBreak
    if showStructure
        label.new(bar_index, low, marketTrend == -1 ? "CHoCH" : "BOS", style=label.style_label_up, color=marketTrend == -1 ? color.teal : color.green, textcolor=color.white, size=size.tiny)
    highBroken := true
    marketTrend := 1

if bearBreak
    if showStructure
        label.new(bar_index, high, marketTrend == 1 ? "CHoCH" : "BOS", style=label.style_label_down, color=marketTrend == 1 ? color.orange : color.red, textcolor=color.white, size=size.tiny)
    lowBroken := true
    marketTrend := -1

//━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// LIQUIDITY SWEEPS
//━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
var bool highSwept = false
var bool lowSwept = false

if not na(pivotHigh)
    highSwept := false

if not na(pivotLow)
    lowSwept := false

bearSweep = barstate.isconfirmed and not na(swingHigh) and high > swingHigh and close < swingHigh and not highSwept
bullSweep = barstate.isconfirmed and not na(swingLow) and low < swingLow and close > swingLow and not lowSwept

if bearSweep
    highSwept := true

if bullSweep
    lowSwept := true

plotshape(showSweeps and bullSweep, title="Bullish Liquidity Sweep", text="Sweep", style=shape.circle, location=location.belowbar, color=color.lime, textcolor=color.black, size=size.tiny)
plotshape(showSweeps and bearSweep, title="Bearish Liquidity Sweep", text="Sweep", style=shape.circle, location=location.abovebar, color=color.red, textcolor=color.white, size=size.tiny)

//━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// FAIR VALUE GAPS
//━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
bullFVG = barstate.isconfirmed and bar_index >= 2 and low > high[2]
bearFVG = barstate.isconfirmed and bar_index >= 2 and high < low[2]

var box bullGap = na
var box bearGap = na

if showFVG and bullFVG
    if not na(bullGap)
        box.delete(bullGap)
    bullGap := box.new(left=bar_index - 2, top=low, right=bar_index + fvgExtend, bottom=high[2], xloc=xloc.bar_index, bgcolor=color.new(color.aqua, 88), border_color=color.new(color.aqua, 45), text="Bull FVG", text_color=color.aqua, text_size=size.tiny)

if showFVG and bearFVG
    if not na(bearGap)
        box.delete(bearGap)
    bearGap := box.new(left=bar_index - 2, top=low[2], right=bar_index + fvgExtend, bottom=high, xloc=xloc.bar_index, bgcolor=color.new(color.orange, 88), border_color=color.new(color.orange, 45), text="Bear FVG", text_color=color.orange, text_size=size.tiny)

//━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// CONFLUENCE ENTRY SIGNALS
//━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// Signals require a structure break OR a liquidity sweep,
// RSI confirmation, and optional candle confirmation.
bullSetup = (bullBreak or bullSweep) and bullMomentum and bullCandleOK
bearSetup = (bearBreak or bearSweep) and bearMomentum and bearCandleOK

var int lastBuyBar = na
var int lastSellBar = na

buyAllowed = na(lastBuyBar) or bar_index - lastBuyBar > cooldown
sellAllowed = na(lastSellBar) or bar_index - lastSellBar > cooldown

buySignal = barstate.isconfirmed and bullSetup and buyAllowed
sellSignal = barstate.isconfirmed and bearSetup and sellAllowed

if buySignal
    lastBuyBar := bar_index

if sellSignal
    lastSellBar := bar_index

plotshape(showSignals and buySignal, title="Apex BUY", text="BUY", style=shape.labelup, location=location.belowbar, color=color.green, textcolor=color.white, size=size.small)
plotshape(showSignals and sellSignal, title="Apex SELL", text="SELL", style=shape.labeldown, location=location.abovebar, color=color.red, textcolor=color.white, size=size.small)

//━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// ATR TARGET MANAGEMENT
//━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
var float activeTarget = na
var int activeDirection = 0
var int activeEntryBar = na
var bool targetHit = false
var line targetLine = na
var label targetLabel = na

if buySignal
    activeDirection := 1
    activeTarget := close + atrValue * atrMult
    activeEntryBar := bar_index
    targetHit := false

    if not na(targetLine)
        line.delete(targetLine)
    if not na(targetLabel)
        label.delete(targetLabel)

    if showTargets
        targetLine := line.new(bar_index, activeTarget, bar_index + targetLength, activeTarget, color=color.lime, style=line.style_dashed, width=2)
        targetLabel := label.new(bar_index + targetLength, activeTarget, "BUY TARGET", style=label.style_label_left, color=color.green, textcolor=color.white, size=size.tiny)

if sellSignal
    activeDirection := -1
    activeTarget := close - atrValue * atrMult
    activeEntryBar := bar_index
    targetHit := false

    if not na(targetLine)
        line.delete(targetLine)
    if not na(targetLabel)
        label.delete(targetLabel)

    if showTargets
        targetLine := line.new(bar_index, activeTarget, bar_index + targetLength, activeTarget, color=color.red, style=line.style_dashed, width=2)
        targetLabel := label.new(bar_index + targetLength, activeTarget, "SELL TARGET", style=label.style_label_left, color=color.red, textcolor=color.white, size=size.tiny)

buyTargetHit = barstate.isconfirmed and activeDirection == 1 and not targetHit and not na(activeTarget) and not na(activeEntryBar) and bar_index > activeEntryBar and high >= activeTarget
sellTargetHit = barstate.isconfirmed and activeDirection == -1 and not targetHit and not na(activeTarget) and not na(activeEntryBar) and bar_index > activeEntryBar and low <= activeTarget

targetHitNow = buyTargetHit or sellTargetHit

if targetHitNow
    targetHit := true
    label.new(bar_index, activeTarget, "TARGET HIT", style=activeDirection == 1 ? label.style_label_down : label.style_label_up, color=color.blue, textcolor=color.white, size=size.tiny)

//━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// ALERTS
//━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
alertcondition(buySignal, title="Apex BUY Signal", message="Apex Confluence Engine BUY on {{ticker}} at {{close}}")
alertcondition(sellSignal, title="Apex SELL Signal", message="Apex Confluence Engine SELL on {{ticker}} at {{close}}")
alertcondition(bullBreak, title="Bullish BOS / CHoCH", message="Bullish market structure break on {{ticker}} at {{close}}")
alertcondition(bearBreak, title="Bearish BOS / CHoCH", message="Bearish market structure break on {{ticker}} at {{close}}")
alertcondition(bullSweep, title="Bullish Liquidity Sweep", message="Bullish liquidity sweep on {{ticker}} at {{close}}")
alertcondition(bearSweep, title="Bearish Liquidity Sweep", message="Bearish liquidity sweep on {{ticker}} at {{close}}")
alertcondition(bullFVG, title="Bullish FVG", message="Bullish fair value gap formed on {{ticker}}")
alertcondition(bearFVG, title="Bearish FVG", message="Bearish fair value gap formed on {{ticker}}")
alertcondition(buyTargetHit, title="BUY Target Hit", message="Apex BUY ATR target reached on {{ticker}} at {{close}}")
alertcondition(sellTargetHit, title="SELL Target Hit", message="Apex SELL ATR target reached on {{ticker}} at {{close}}")
